/**************************************************************************************
 *  Copyright (c)  2010  Leszek Karcz, Changmin Bae.
 *  Permission is granted to copy, distribute and/or modify this document
 *  under the terms of the GNU Free Documentation License, Version 1.3
 *  or any later version published by the Free Software Foundation;
 *  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 *  A copy of the license is included in the section entitled "GNU
 *  Free Documentation License". 
 **************************************************************************************/
package data.tileables;
import data.LinkedList;
import data.Map;
import data.Player;
import data.StructLinkedList;
import data.Tile;
import data.UnitOwner;
import data.missions.BuildExplorer;
import data.missions.BuildWorker;
import data.missions.Heal;
import data.missions.PowerDown;
import data.missions.PowerUp;
import data.missions.UnassignAll;
import data.missions.UnassignAllFromBase;


/**************************************************************************************
 * Author(s): Leszek Karcz, Changmin Bae
 * Base building, the main building for a player
 **************************************************************************************/
public class Base extends HarvestStructure implements UnitOwner
{
	
	public static final int [] PRICE = { 0, 0, 0 };
	private StructLinkedList metal = new StructLinkedList(METAL);
	private StructLinkedList energy = new StructLinkedList(ENERGY);;
	private StructLinkedList food = new StructLinkedList(FOOD);
	private int selectedResource = 0;
	private boolean meeleFlag=false;
	private int healRate = 3;
	private LinkedList<Unit> assignedUnits=new LinkedList<Unit>();	
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz, Changmin Bae
	 * Base constructor
	 **************************************************************************************/
	public Base(int ID, int supertypeID, Player player){this(ID, supertypeID, player, 5);}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz, Changmin Bae
	 * Base contructor X2
	 **************************************************************************************/
	public Base(int ID, int supertypeID, Player player, int workers){
		super(ID, supertypeID, player, workers);
		this.setType("Base");
		this.setImage("struct_base");
		this.setIcon("struct_base");
		this.setStats(11, 1.82, 100, 50, 0, 10, 1);
		this.setUpkeep(new int[]{1,1,1});
		this.setNumberOfCommands(7);
		
		player.changeWorkerCount(5);
	}
	
	/**************************************************************************************
	 * Author(s): Eric Martin-Taylor
	 * Removes a unit from the list.
	 * 		True = unit was removed
	 * 		False = unit was in in rally
	 **************************************************************************************/
	public boolean removeUnit(Unit unit)
	{		
		if(this.assignedUnits.remove(unit)==null)
		{
			return false;
		}
		return true;		
	}
	
	/**************************************************************************************
	 * Author(s): Leszek Karcz
	 * adds the unit to the list
	 **************************************************************************************/
	public boolean addUnit(Unit unit)
	{		
		if(!this.assignedUnits.find(unit))
		{
			this.assignedUnits.addBack(unit);
			return true;
		}
		return false;
	}	
	
	/**************************************************************************************
	 * Author(s): Changmin Bae
	 * executes instructions regarding currently selected command
	 **************************************************************************************/
	public boolean enqueueSelectedCommand(String mode, Map m, int x, int y)
	{
		int selected=this.getSelectedCommand();
		if(this.isFinished())
		{
			if((this.getCommandMode()==0) && (mode.equals("Issue")))
			{
				switch(selected)
				{
					case 0:
						this.die();
						break;
					case 1:
						if(this.getState() == 0)
							this.addMission(new PowerUp(this));
						else
							this.addMission(new PowerDown(this));
						break;
					case 2:
						if(this.getState() == 1)
						{
							this.addMission(new BuildExplorer(this, m, player));
						}
						break;
					case 3:
						this.setCommandMode(2);
						break;
					case 4:
						if(this.getState() == 1)
						{
							this.addMission(new UnassignAllFromBase(this));
						}
						break;
					
					case 5:
						if(this.getState() == 1)
						{
							this.addMission(new Heal(m,this, player));
						}
						break;
						
					case 6:
						if(this.getState() == 1)
						{
							this.addMission(new BuildWorker(this,m, player));
							this.addWorkers(5);
						}
						break;
						
				}
			}
			else if(this.getCommandMode()==1)
			{
				if(mode.equals("Issue"))
				{
					this.setCommandMode(0);
					this.assignWorkers(this.getCommandValue(), m, x, y, selectedResource);// 
					this.setCommandValue(0);
				}
				else
				{
					boolean flag=false;
					try  
					{  
						Integer.parseInt(mode);  
						flag=true;
					}  
					catch(Exception e){}  
					if(flag)
					{
						this.setCommandValue(Integer.parseInt(mode));
					}
				}
			}
			else if(this.getCommandMode()==2)
			{
				int currSelection = this.getSelectedCommand();
				if(mode.equals("Issue"))
				{
					switch(currSelection)
					{
					case 0:						
						selectedResource = 0;
						this.setCommandMode(1);
						break;
					case 1:
						selectedResource = 1;
						this.setCommandMode(1);
						break;
					case 2:
						selectedResource = 2;
						this.setCommandMode(1);
						break;
					}
				}
			}
		}
		else
		{
			switch(selected)
			{
				case 0:
					if(this.player.createColonyShip(this.getX(), this.getY(), this.getWorkerCount()))
					{
						this.player.changeWorkerCount(-this.getWorkerCount());
						this.die();
					}
			}
		}
		return true;
	}
	/**************************************************************************************
	 * Author(s): Changmin Bae
	 * returns metal resource list
	 **************************************************************************************/
	public StructLinkedList getMetalList()
	{
		return metal;
	}
	/**************************************************************************************
	 * Author(s): Changmin Bae
	 * returns food resource list
	 **************************************************************************************/
	public StructLinkedList getFoodList()
	{
		return food;
	}
	/**************************************************************************************
	 * Author(s): Changmin Bae
	 * returns energy resource list
	 **************************************************************************************/
	public StructLinkedList getEnergyList()
	{
		return energy;
	}
	/**************************************************************************************
	 * Author(s): Changmin Bae
	 * returns list of possible commands
	 **************************************************************************************/
	public String[] getCommandsText()
	{
		if(this.isFinished())
		{
			if(this.getCommandMode() == 0)
			{
				return new String[]{"Decommision",(this.getState()==0 ? "Power up" : "Power down"),"Build explorer","Assign workers","Unassign all","Heal","Breed Workers"};
			}
			else if(this.getCommandMode()==1)
			{
				return new String[]{"Workers: "+this.getCommandValue()};
			}
			else if(this.getCommandMode()==2)
			{
				return new String[]{"Food","Metal", "Energy"};
			}
			else
			{
				 return new String[]{"---"};
			}
		}
		else
		{
			return new String[]{"Cancel"};
		}
	}
	/**************************************************************************************
	 * Author(s): Changmin Bae
	 * returns number of commands
	 **************************************************************************************/
	public int getNumberOfCommands()
	{
		if(this.getCommandMode()==0)
		{	
			return super.getNumberOfCommands();
		}
		else if(this.getCommandMode()==1)
		{
			return 1;
		}
		else if(this.getCommandMode()==2)
		{
			return 3;
		}
		else
		{
			return 1;
		}
		
	}
	
	/**************************************************************************************
	 * Author(s): Eric Martin-Taylor
	 * returns an array of the harvested resources
	 **************************************************************************************/
	public int[] harvest()
	{
		int [] temp = new int[3];
		temp[FOOD] = food.harvest();
		temp[METAL] = metal.harvest();
		temp[ENERGY] = energy.harvest();
		
		return temp;
	}
	
	@Override
	public void die()
	{ 
		super.die();
		player.removeBase(this);
	}
	
	/**************************************************************************************
	 * Author(s): Changmin Bae
	 * Assigns workers
	 **************************************************************************************/
	public boolean assignWorkers(int workers, Map map, int x, int y, int type)
	{
		if(!(map.checkRadius(this.getX(), getY(), x, y, this.getVisionRadius())))
			return false;		
		Tile temp = map.getTile(x, y);		
		if(temp.getResources() == null)
			return false;
		workers = this.decUnassignedWorkers(workers);		
		if(workers == 0)
		{
			if(type==FOOD){
				incUnassignedWorkers(food.unassignAllWorkers());
			}
			else if(type==METAL){
				incUnassignedWorkers(metal.unassignAllWorkers());
			}
			else{
				incUnassignedWorkers(energy.unassignAllWorkers());
			}
		}
		else
		{			
			if(type==FOOD){
				food.addResource(temp.getResources(), this);
				food.assignWorkers(workers, temp.getResources());
			}
			else if(type==METAL){
				metal.addResource(temp.getResources(), this);
				metal.assignWorkers(workers, temp.getResources());
			}
			else{
				energy.addResource(temp.getResources(), this);
				energy.assignWorkers(workers, temp.getResources());
			}
		}
		
		return true;		
	}
	public int getHealRate()
	{
		return healRate;
	}
	public void execute()
	{
		super.execute();
		if(!this.meeleFlag)
		{
			if(this.isFinished())
			{
				this.player.createMelee(this.getX(), this.getY());
				this.player.createMelee(this.getX(), this.getY());
				this.meeleFlag=true;
			}
		}
	}

}
